package com.xiaozhu.controller;

import com.xiaozhu.common.aiconstant.LockConstants;
import com.xiaozhu.enumreation.LockState;
import com.xiaozhu.enumreation.RedisKeyEnum;
import com.xiaozhu.enumreation.RoleRedisEnum;
import com.xiaozhu.pojo.dto.ChatDto;
import com.xiaozhu.pojo.result.Result;
import com.xiaozhu.pojo.vo.ChatPair;
import com.xiaozhu.pojo.vo.MessageVo;
import com.xiaozhu.repository.Impl.InMemoryChatHistoryRepository;
import com.xiaozhu.server.ChatContentServer;
import com.xiaozhu.utils.RedisLockTemplate;
import com.xiaozhu.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.messages.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.stream.Collectors;

/**
 * ChatHistoryController
 *
 * 处理聊天历史相关接口，包括获取会话ID列表和会话消息列表
 *
 * @author 朱慧军
 * @version 1.0
 */
@RestController
@RequestMapping("/ai/history") // 定义控制器基础路径
@Slf4j // Lombok 注解，自动生成日志对象 log
public class ChatHistoryController {

    @Autowired
    private InMemoryChatHistoryRepository inMemoryChatHistoryRepository;
    // 注入自定义的内存聊天历史仓库，用于获取保存的聊天会话ID

    @Autowired
    private ChatMemory chatMemory;
    // 注入 Spring AI 内存聊天对象（OpenAI 或 Ollama），可获取自动保存的聊天消息

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private ChatContentServer chatContentServer;

    @Autowired
    private RedisLockTemplate redisLockTemplate;

    /**
     * 获取指定类型的聊天会话ID列表
     * URL 示例: GET /ai/history/type?type=chat
     */
    @GetMapping("/type")
    public List<Integer> getChatId(ChatDto dto){
        // 从内存 + Redis + DB 获取指定类型的聊天ID列表
        List<Integer> chtIds = inMemoryChatHistoryRepository.getChtIds(dto);
        List<Integer> list = chtIds.stream().distinct().toList();
        log.info("chatid:{}",list);
        return list; // 返回给前端
    }

    /**
     * 获取指定聊天会话的消息列表
     * URL 示例: GET /ai/history/type/conversation?chatId=1&type=chat
     */
    @GetMapping("/type/conversation")
    public List<MessageVo> getChatConversation( ChatDto chatDto){
        // 验证参数
        if (chatDto.getChatId() == null) {
            log.error("chatId 为空，无法查询对话历史");
            return List.of();
        }
        
        // 转为 String 类型，与保存时保持一致
        String chatId = chatDto.getChatId().toString();
        log.info("查询对话历史，chatId: {}", chatId);

        // 从 ChatMemory 中获取指定会话ID的消息列表，Integer.MAX_VALUE 表示获取所有消息
        List<Message> messages = chatMemory.get(chatId, Integer.MAX_VALUE);

        log.info("从 ChatMemory 获取到 {} 条消息", messages.size());

        if (messages.isEmpty()){
            log.warn("chatId {} 没有找到历史消息，可能原因：1.应用重启导致内存清空 2.chatId不匹配 3.确实没有发送过消息", chatId);
            return List.of(); // 如果没有消息，返回空列表
        }

        // 将 Message 对象列表转换为 MessageVo 对象列表
        return messages.stream() // 1. 将 messages 列表转换为 Stream 流，方便链式操作
                .map(MessageVo::new) // 2. 使用 MessageVo 的构造函数将 Message 对象转换为 MessageVo 对象
                .collect(Collectors.toList()); // 3. 将处理后的流元素收集成一个 List 返回

    }

    @GetMapping("/type/content")
    public Result<String> content(@RequestParam Integer chatTypeId){

        log.info("获取历史记录：{}",chatTypeId);
        if (chatTypeId == null){
            log.warn("chatTypeId不可以为空");
            throw new RuntimeException("chatTypeId不可以为空");
        }
        // 锁的名字
        String key = LockConstants.LOCKED_KEY  + chatTypeId;
        // 锁的唯一标识符
        String requested = chatTypeId.toString();
        String keyUser = RedisKeyEnum.REDIS_KEY_CONTENT.keyTyp() + RoleRedisEnum.ROLE_USERC.getName();
        String keyModel = RedisKeyEnum.REDIS_KEY_CONTENT.keyTyp() + RoleRedisEnum.ROLE_MODEL.getName();

        ChatPair chatPair = redisLockTemplate.executeWithLock(key, requested, () -> {
             String user = redisUtils.get(keyUser, String.class);
             String model = redisUtils.get(keyModel, String.class);
            return new ChatPair(user, model);
        });

        if ( chatPair == null){
            log.info("redis中获取失败，可能被清除");
            String content = chatContentServer.content(chatTypeId);
            // 写回 Redis 缓存（可选：设置过期时间 1 小时）
            redisUtils.set(keyUser, content);
            return Result.success(content);

        }

        log.info("userContent:{}, modelContent:{}",chatPair.userContent(), chatPair.modelContent());


        StringBuilder content = new StringBuilder();
        content.append("会话id:")
                .append(chatTypeId)
                .append("\n 用户：")
                .append(chatPair.userContent())
                .append("\n 模型")
                .append(chatPair.modelContent())
                .append("\n\n");
        log.info("用redis中获取的：{}",content);

        return Result.success(content.toString());

    }

}
